PRELOADER

不念过去 不负现在 不畏将来

当前文章 : 《STM32 systick时钟》

12/4/2018 —— 

STM32 systick时钟

项目说明

之前使用的延迟函数是利用循环语句占用cpu时间来实现的,这样的延时并不准确。而systick定时器是包含在M3的内核里,捆绑在 NVIC 中的。使用它可以做到很精确的延时。

知识点

  • 1、它是24位倒计数的定时器,当定时器 进行减1 计数到0的时候,将从LOAD寄存器中 自动重装 定时器初值,如果开启中断的话,同时它还是产生异常中断信号。默认使用的为系统的72M频率进行8分频得到的9Mhz。
  • 2、systick定时器的时钟来源是来自系统时钟,不过它的时钟可以选择成直接取自系统时钟,还可以将系统时钟8分频之后再赋给systick定时器。但是该定时器的时钟频率可随系统时钟频率的变化而改变。而STM32这个芯片本身就可以设定不同的晶振源并设置不同的系统频率,所以该定时器的工作频率是随系统频率而变的。
  • 3、它的功能由4个寄存器来决定。其中,寄存器LOAD负责记录初值,寄存器VAL负责记录当前值。 这两个寄存器均为24位寄存器,所以其 大计数值为0xffffff 。因此,在使用默认的9Mhz频率时,延迟时间理论上最大可到(0xffffff/9000)秒,即1.864秒。 因此在进行延迟时,一般只延迟1秒,要延迟2秒则调用两次延迟函数就好。

部分代码

  • 1、延迟微秒函数,延迟毫秒为乘以9000.
void delay_us(u32 i)
{
    u32 temp;
    SysTick->LOAD=9*i;         //在9Mhz的频率下,意味着每为妙执行9次,因此需要乘以9
    SysTick->CTRL=0X01;         //控制寄存器最低位为打开systick
    SysTick->VAL=0;                //当前值清零
    do
    {
        temp=SysTick->CTRL;           
    }
    while((temp&0x01)&&(!(temp&(1<<16))));     //判断是否计数完成
    SysTick->CTRL=0;    //关闭systick
    SysTick->VAL=0;        //当前计数值清零
}
  • 2、自定义时钟频率
void RCC_HSE_Configuration() //自定义系统时间(可以修改时钟)
{
    RCC_DeInit(); //将外设RCC寄存器重设为缺省值
    RCC_HSEConfig(RCC_HSE_ON);//设置外部高速晶振(HSE)
    if(RCC_WaitForHSEStartUp()==SUCCESS) //等待HSE起振
    {
        RCC_HCLKConfig(RCC_SYSCLK_Div1);//设置AHB时钟(HCLK)
        RCC_PCLK1Config(RCC_HCLK_Div2);//设置低速AHB时钟(PCLK1)
        RCC_PCLK2Config(RCC_HCLK_Div1);//设置高速AHB时钟(PCLK2)
        RCC_PLLConfig(RCC_PLLSource_HSE_Div2,RCC_PLLMul_9);//设置PLL时钟源及倍频系数
        RCC_PLLCmd(ENABLE); //使能或者失能PLL
        while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET);//检查指定的RCC标志位设置与否,PLL就绪
        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);//设置系统时钟(SYSCLK)
        while(RCC_GetSYSCLKSource()!=0x08);//返回用作系统时钟的时钟源,0x08:PLL作为系统时钟
    }
}

2017/11/19 更新

  • 1、在较新的库函数版本中,systick用于延时的时候是非常实用的,而且配置上也比较简单。都是根据系统主频的配置自动设置初始计数值,将定时器的定时时间设置成1ms。
  • 2、1ms产生一次中断,在中断函数中执行计数值uwTick加1操作。
  • 3、延迟函数中通过对uwTick的数值进行判断来实现。这样在延迟时也可以比较灵活,对参数i(单位为ms)传值便可以配置延迟时间。代码如下:
      __weak void HAL_Delay(__IO uint32_t Delay)
      {
        uint32_t tickstart = 0U;
        tickstart = HAL_GetTick();
        while((HAL_GetTick() - tickstart) < Delay)
        {
        }
      }